package com.geeke.config.crypto;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.apache.catalina.Engine;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Valve;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.AprLifecycleListener;
import org.apache.catalina.startup.Tomcat;
import org.apache.tomcat.util.modeler.Registry;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServer;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.core.NativeDetector;
import org.springframework.util.Assert;

public class CryptoTomcatServletWebServerFactory extends TomcatServletWebServerFactory {
    private boolean disableMBeanRegistry = true;
    private File baseDirectory;
    private String protocol = DEFAULT_PROTOCOL;
    private int backgroundProcessorDelay;

    @Override
    public void setDisableMBeanRegistry(boolean disableMBeanRegistry) {
		this.disableMBeanRegistry = disableMBeanRegistry;
        super.setDisableMBeanRegistry(disableMBeanRegistry);
	}

    @Override
	public void setBaseDirectory(File baseDirectory) {
		this.baseDirectory = baseDirectory;
        super.setBaseDirectory(baseDirectory);
	}

    @Override
    public void setProtocol(String protocol) {
		Assert.hasLength(protocol, "Protocol must not be empty");
		this.protocol = protocol;
        super.setProtocol(protocol);
	}

    @Override
	public void setBackgroundProcessorDelay(int delay) {
		this.backgroundProcessorDelay = delay;
        super.setBackgroundProcessorDelay(delay);
	}

    @Override
	public WebServer getWebServer(ServletContextInitializer... initializers) {
		if (this.disableMBeanRegistry) {
			Registry.disableRegistry();
		}
		Tomcat tomcat = new Tomcat();
		File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
		tomcat.setBaseDir(baseDir.getAbsolutePath());
		for (LifecycleListener listener : this.getDefaultServerLifecycleListeners()) {
			tomcat.getServer().addLifecycleListener(listener);
		}
        // 加密tomcat链接
		Connector connector = new CryptoConnector(this.protocol);
		connector.setThrowOnFailure(true);
		tomcat.getService().addConnector(connector);
		customizeConnector(connector);
		tomcat.setConnector(connector);
		tomcat.getHost().setAutoDeploy(false);
		configureEngine(tomcat.getEngine());
		for (Connector additionalConnector : this.getAdditionalTomcatConnectors()) {
			tomcat.getService().addConnector(additionalConnector);
		}
		prepareContext(tomcat.getHost(), initializers);
		return getTomcatWebServer(tomcat);
	}

    private static List<LifecycleListener> getDefaultServerLifecycleListeners() {
		ArrayList<LifecycleListener> lifecycleListeners = new ArrayList<>();
		if (!NativeDetector.inNativeImage()) {
			AprLifecycleListener aprLifecycleListener = new AprLifecycleListener();
			if (AprLifecycleListener.isAprAvailable()) {
				lifecycleListeners.add(aprLifecycleListener);
			}
		}
		return lifecycleListeners;
	}

    private void configureEngine(Engine engine) {
		engine.setBackgroundProcessorDelay(this.backgroundProcessorDelay);
		for (Valve valve : this.getEngineValves()) {
			engine.getPipeline().addValve(valve);
		}
	}
}
